use std::collections::HashMap;

use hex_literal::hex;
use parlia_types::ValidatorsBitSet;
use unionlabs_primitives::{Bytes, H256};

use super::*;

#[derive(Clone)]
struct BlstContext {
    current_timestamp: Timestamp,
    epoch_valsets: HashMap<u64, Valset>,
}

// will never be BLST_SUCCESS
#[derive(Debug, Clone, thiserror::Error)]
#[error("{0:?}")]
pub struct BlstError(blst::BLST_ERROR);

impl BlstError {
    fn new_result(e: blst::BLST_ERROR) -> Result<(), Self> {
        if e == blst::BLST_ERROR::BLST_SUCCESS {
            Ok(())
        } else {
            Err(Self(e))
        }
    }

    fn new(e: blst::BLST_ERROR) -> Self {
        Self::new_result(e).unwrap_err()
    }
}

impl VerificationContext for BlstContext {
    type Error = BlstError;

    fn current_timestamp(&self) -> Timestamp {
        self.current_timestamp
    }

    fn get_valset(&self, epoch_block_number: u64) -> Result<Valset, Self::Error> {
        Ok(self.epoch_valsets.get(&epoch_block_number).unwrap().clone())
    }

    fn verify<'pk>(
        &self,
        public_keys: impl IntoIterator<Item = &'pk H384>,
        msg: &[u8],
        signature: H768,
    ) -> Result<(), Self::Error> {
        let agg_sig =
            blst::min_pk::Signature::uncompress(signature.get()).map_err(BlstError::new)?;

        BlstError::new_result(
            agg_sig.fast_aggregate_verify(
                true,
                msg,
                b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_",
                &public_keys
                    .into_iter()
                    .map(|pkey| {
                        blst::min_pk::PublicKey::uncompress(pkey.get()).map_err(BlstError::new)
                    })
                    .collect::<Result<Vec<_>, _>>()?
                    .iter()
                    .collect::<Vec<_>>(),
            ),
        )
    }
}

#[track_caller]
fn deser_header(json: &str) -> ParliaHeader {
    serde_json::from_str(json).unwrap()
}

#[test]
fn verify_header_works_testnet() {
    // 55475596
    let source = deser_header(
        r#"{"parentHash":"0xdd0eaf7f4e73b61b6b232358e235ee879b8e321d7c8f976c4242db55275c80a2","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x90409f56966b5da954166eb005cb1a8790430ba1","stateRoot":"0x8cd0286815e0e5afc095bf6a1aed01e82e906f23b8f8536149a31e0d42c0b01c","transactionsRoot":"0x406e687cb846a88d971394b5f1927ef01287cd8c0a2cfe20817d345517f78d38","receiptsRoot":"0x90bb10b203eb8e2462bff1cc0a0055b20d74f7d31b354243dd1950b06cf30c80","logsBloom":"0x000008004000000000010040000020000020400000000000000002000000000000001080000000000000000000000000000800000000000000000000002000000040000400800000000000081000000022100002000000000000000000100002000810200002000000000000010000000a0000000000000000000010000000000000002000000000000000000002000001000400004000008400000000000020020000000000002008000000028000000000000000000000000000000000000000000002000000000000140000000000000000000000001000104002000000000010800000000000010000040000010000008000000000004100000000001000","difficulty":"0x2","number":"0x34e7d8c","gasLimit":"0x5e29eed","gasUsed":"0x83351","timestamp":"0x6855884c","extraData":"0xd88301050d846765746888676f312e32332e39856c696e757800000038469028f8b27fb860a721d42755113b5cbdac611e235d97b9119eb22a44b9e14c0be9db09726ca0e4daad7b0897608eba03e70d8bb516ed740257857fbaa2f7d2213eeba4f4481b62b8fe89de0ef1a562abc3ff84810b38647420407ebf0847d048148afbf523c051f84c84034e7d8aa06e1316485b6da89f3d4c0e434d9206488843a4a9e54462ab8746976e57822dfd84034e7d8ba0dd0eaf7f4e73b61b6b232358e235ee879b8e321d7c8f976c4242db55275c80a280f33ec24f7c83f578fcd505ae3a1b83c424f04098df9382b97cc81d5f28221d6b67c789880790fc9427d2e156bb9ad51eeb4efa479fa429cf4f1f11263a3cbdd700","mixHash":"0x00000000000000000000000000000000000000000000000000000000000000fa","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let target = deser_header(
        r#"{"parentHash":"0x053e82c0a815b741826b338cb3fd1346a098ea0d69dcca5f56673731279be1db","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x90409f56966b5da954166eb005cb1a8790430ba1","stateRoot":"0x1677499391845cd0e4913642a3f0353063771425a85ce440b3682e12b2c06757","transactionsRoot":"0xd0dd7a6c34eed0e99104d34f21a11aa2cbe1cad2d7c2677db297fe921b870d6f","receiptsRoot":"0x0dde1b798eff095db7ca4693cb1203d74da3430698e9acdc914fa7513e4d2127","logsBloom":"0x00000000400000000000004000002000000000000800000000000200000000000000108000000000000000000000000010000000000000000000000000200000000000000080100000000008100000002010000000000000000000000000000200080020000200000000000001000000080400000010000000000010000000000000000000000000000000000002000000000400000000008000000000000020020000002000002008000000020000000000000000000000008000000000000000000002000000000004140000000000000000000000001000104002000000000010000000000000010000040000010000008000000000004101000000001000","difficulty":"0x2","number":"0x34e7d8d","gasLimit":"0x5e12647","gasUsed":"0x5c027","timestamp":"0x6855884d","extraData":"0xd88301050d846765746888676f312e32332e39856c696e757800000038469028f8b27fb86097ecebb7fe6367c2f85d8fae3eeef6b0f2d1fe572a8671e078259179fe7d72e6b216eb8ce017b281bcb5e7c837f4fa41095b7c7f8089be29478774536b76f5dc63f404b943f184f8c58fc326979fc8dfebc3802cd8f762e1c2a4b169bbcdacaef84c84034e7d8ba0dd0eaf7f4e73b61b6b232358e235ee879b8e321d7c8f976c4242db55275c80a284034e7d8ca0053e82c0a815b741826b338cb3fd1346a098ea0d69dcca5f56673731279be1db806e89d76116b905e9585ed4a1870491457cd08f1cfad09fcb89c0557bf5e7d7f420b8c480a6dfac71c9ac4454b459041626e4f539e912ccf5bf6392733307dcbc00","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let attestation = deser_header(
        r#"{"parentHash":"0xc28a31508a6f9c7376bc49e9b28529e3316dbc4e23205eacfb552ca4c7aecc97","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x90409f56966b5da954166eb005cb1a8790430ba1","stateRoot":"0x7810faeda27cf9c2b482a323b6b0daf1b091da489dfea387299291097ec63841","transactionsRoot":"0x558ca0974f34670318eebfee8d1b4297c5833b3b46a420fb5e7b1b8368061c20","receiptsRoot":"0xf2a9868aa55b9876f43acfe14f47615f0ac8326a073cc51d509e39460da2dea0","logsBloom":"0x00000000400000000000004000002800000000000000000000000280000000200000108000000000000000000010000000000000000000000000000000200000004000000080008000000008100000002010000000000000000000000000000200080020000200000000000001000000080000000000000000000010000000000000000000000000000000002002200008000400000000008000000000000020020000000000002008200040020000000000000000000000000000000000000000000002000000000000140000000000000000000000003100104002000000000010000000200000010000040000010010008000000000004100000000001000","difficulty":"0x2","number":"0x34e7d8e","gasLimit":"0x5dfadff","gasUsed":"0x62181","timestamp":"0x6855884d","extraData":"0xd88301050d846765746888676f312e32332e39856c696e757800000038469028f8b27fb86096617b60a045db74aa4db769a554c4e5c7629a78b8f8b93534fca11d1cc6602c51c3686dd8c07810d28c4b84e894598d02063576968638fdd715e3c5bb6a6236df3cd8fb66a48ee7994a2ad746f10f77f1cb031976d1258ab199aeb60d7694f3f84c84034e7d8ca0053e82c0a815b741826b338cb3fd1346a098ea0d69dcca5f56673731279be1db84034e7d8da0c28a31508a6f9c7376bc49e9b28529e3316dbc4e23205eacfb552ca4c7aecc9780795dadc6947ae45cd4cde727de61d5755ba6da14d26d4192a2709fc333f94d5640780856238690e3b2aea2c97335495713a26878f6839b6fdb6bf8a154b67a5700","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x20000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    let (_, valset) = parse_epoch_rotation_header_extra_data(&hex!("d883010510846765746888676f312e32332e39856c696e7578000000384690280708265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10f8b27fb860a18a293898150b2c5c7112c7cd482121e3a50f30b03a4fa9bb39cac2397b2058089eb019af04dc6c43a59189f6a438400fc612012b27a9df59a91531b3cc36b75dbdd51008f61a7bf4a0c7da5fe2b7df9eefa6e9c42b9dedca7f32bcb6edc907f84c84034e7b36a0d40e88dd0303dd4ca0772ba4e9c5d36b82f4e526bd294f2cd98b1b45886a60ea84034e7b37a0def92aee98a20bf20f2c7a6ddc5807700a95353c75c2f7b9329c9be2d1e6a6c480c692716571c53a20a0de653cefffd0da1d1c092d01e47a96daa1195431420b453cb0e01350b790d8523a7c3ef4edffeb776187c57e1c96a06ebc582baabc889301")).unwrap();

    let chain = [source.clone(), target, attestation];
    let res = verify_header(
        &chain,
        Duration::from_secs(604800),
        55475000,
        BlstContext {
            current_timestamp: Timestamp::from_nanos(1750435993000000000),
            epoch_valsets: [(55475000_u64, valset)].into_iter().collect(),
        },
    )
    .unwrap();

    assert_eq!(res, (&source, None));
}

#[test]
fn verify_header_works_valset_rotation_testnet() {
    // 55475000
    let source = deser_header(
        r#"{"parentHash":"0xdef92aee98a20bf20f2c7a6ddc5807700a95353c75c2f7b9329c9be2d1e6a6c4","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x76d76ee8823de52a1a431884c2ca930c5e72bff3","stateRoot":"0x2252dded282328d3057a456ee699c2e68f4ee62dbdb0caab780a7a68946a4b9f","transactionsRoot":"0xd6248fa40389110b461656d1d2d466a15d5fde590d2da9c5a12252bf8f9c672c","receiptsRoot":"0x9933ab2eae9c3cf424fccfec480ecafed7dc7507c4d97a9a1ea526337af8506c","logsBloom":"0x040000004000040000000040000020000a0000000000001000000200020000000000108000000000008030400800000000000000000001000000000020200000000001000081000100000008100000a021100000000000000040000000000002000800208202000100000000010008000800240000000000002000100000000000000820000040800200000000060000000004000000000280000000000000200200000000000220080000000280000004000000000010100000000000000000008000020000000000001420000000004000000000000250001048020000240040100000000000000110008c0000010500008000008000004100208000081000","difficulty":"0x2","number":"0x34e7b38","gasLimit":"0x5f5e100","gasUsed":"0x14a393","timestamp":"0x6855868d","extraData":"0xd883010510846765746888676f312e32332e39856c696e7578000000384690280708265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10f8b27fb860a18a293898150b2c5c7112c7cd482121e3a50f30b03a4fa9bb39cac2397b2058089eb019af04dc6c43a59189f6a438400fc612012b27a9df59a91531b3cc36b75dbdd51008f61a7bf4a0c7da5fe2b7df9eefa6e9c42b9dedca7f32bcb6edc907f84c84034e7b36a0d40e88dd0303dd4ca0772ba4e9c5d36b82f4e526bd294f2cd98b1b45886a60ea84034e7b37a0def92aee98a20bf20f2c7a6ddc5807700a95353c75c2f7b9329c9be2d1e6a6c480c692716571c53a20a0de653cefffd0da1d1c092d01e47a96daa1195431420b453cb0e01350b790d8523a7c3ef4edffeb776187c57e1c96a06ebc582baabc889301","mixHash":"0x00000000000000000000000000000000000000000000000000000000000000fa","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let target = deser_header(
        r#"{"parentHash":"0xaeab92600438b508c9ec3528b0952ceffe95a68e7a13dc8b20549c4044f19225","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x76d76ee8823de52a1a431884c2ca930c5e72bff3","stateRoot":"0xe22e98d8250109d6b6583387d9f9dfccf62f099be6af84849da73287a9afca2b","transactionsRoot":"0x7776cbefdcb7ccd45ba8008813eda868b404cdc044eaa9d50d5d44f13dd1a809","receiptsRoot":"0xc1bdcab4a5b74f334b3200241b17ede1ed068933187081946abae4f3e83ecd00","logsBloom":"0x00040000000024000000004000002200080000000000000000000200000000000000108000000000000000000000000000000000000000000000000000000000000000000000000000000008000000002010000000000000000000000000100200080020120200010000000001000800080004000000000000000010000000000020002000000000040000000002000000000400000000028000000000000020000000000000002008000000020000000000000020000000000000000000000000000002000000000020100000000000000080000000001100384002000020000000000000000000010000040000010000008000002000004000000800001000","difficulty":"0x2","number":"0x34e7b39","gasLimit":"0x5f5e100","gasUsed":"0x910b6","timestamp":"0x6855868e","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb860ab01f151428ea696802a2b626fb0e9598c10ccc06bb6e8c4aed9bf6f789c35d300903c2b5db7fe71c0529474ed39cbbb09b938a80eb26801ca8a1db7197294b2f839cbd9aa033cac19adef4f0b2b02e463431b0418b417b10acdd0797ca66d3df84c84034e7b37a0def92aee98a20bf20f2c7a6ddc5807700a95353c75c2f7b9329c9be2d1e6a6c484034e7b38a0aeab92600438b508c9ec3528b0952ceffe95a68e7a13dc8b20549c4044f1922580b8f5f7b3eb35fe7c81590b2913b453a1f49df5eea0fa8b31b9ee64844659a474629acb0618e1abc9c643669630b542ee94274601f0976eb2cab1aa8886fb1a2d00","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let attestation = deser_header(
        r#"{"parentHash":"0xe01078f0512466d0eb277e99de0c78756546768e2ac904ba3f218c726e013c9c","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x76d76ee8823de52a1a431884c2ca930c5e72bff3","stateRoot":"0x09d6c0147c074f080ed141cbf2caf5fdba7310fbd53fe3e4895b3d6f49b54e33","transactionsRoot":"0xf458e35c177806418bcc6f8ee67eeac09472e82c60e57b9e5ce673cd8d66d59f","receiptsRoot":"0x8eb671ae0f8cf30892abf6d2c2c30766290a017d0cb4db4dbab534d0c779ec43","logsBloom":"0x00000000000004000000004000002000080000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000000000000000000000008000000082010000000000000000000000000000200080020020200010000000001000800080004000000000002000010000000000000002000000000000002000002000000000400000000028000000000000020000000000000002008000000020000000000000000000000000000000000000000000802000000000080100000000100000000000000001000104002000020000004000000000000010000040000010000088000000000004000000000001000","difficulty":"0x2","number":"0x34e7b3a","gasLimit":"0x5f5e100","gasUsed":"0x571ae","timestamp":"0x6855868e","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb860a994dcfd43a2e7793332ad42a17d1f1caa916cf900b3ed13f0e757c908e389f3fae08b7e5f0c95f919247491ad7f86050a2d1b5dc199092ffc7aa49227223eb346d1c1e3d7f6a471d03aebb1d678ebd9f9b3bc21aff102e0beadcdeeb1fd0dfff84c84034e7b38a0aeab92600438b508c9ec3528b0952ceffe95a68e7a13dc8b20549c4044f1922584034e7b39a0e01078f0512466d0eb277e99de0c78756546768e2ac904ba3f218c726e013c9c807603ff1db913fab4efdad0969896903683bd92483ae75ecc204a2effce6d4a011c19783f7dbddc5b50abfac6bd1b25bd6c25af6f8853bf834f45abc5fc5d8e8201","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x40000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    let (_, valset) = parse_epoch_rotation_header_extra_data(&hex!("d883010510846765746888676f312e32332e39856c696e7578000000384690280708265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10f8b27fb860939558d8be3f3db29729a2ec0ba2d48ef9be23254980cb49c561d42ba58b4d727a3b4dd69a8df174a876f3ca799f61b60cd66d5dbec0b0c0be4ca3ff0d6e260234fec1b9f6c81f60a2da93831ef39f17230c017daa2cb815bbc2ba5fa84efe2cf84c84034e774ea064fb026e8f5c04e2a642ea5af194bc76961f0c26100fc04e6fe4216e02c867df84034e774fa07ed29e8be587d0d8de91070d0d9d22be22d6b385aa8e5c723e1510526441a5c880dffc3da994d38fe40d51cc4322cd0afe05ae676299b44af2fb2836c41e983baf3cda8ccd4e49392772dfe698f3aaf9a84e2ddd62a81d251784384770feaaa6b501")).unwrap();

    let chain = [source.clone(), target, attestation];
    let res = verify_header(
        &chain,
        Duration::from_secs(604800),
        55474000,
        BlstContext {
            current_timestamp: Timestamp::from_nanos(1750435993000000000),
            epoch_valsets: [(55474000, valset)].into_iter().collect(),
        },
    )
    .unwrap();

    assert_eq!(res.0.number, U256::from(55475000_u64));

    assert_eq!(
        res,
        (
            &source,
            Some((
                source.number.try_into().unwrap(),
                parse_epoch_rotation_header_extra_data(&source.extra_data)
                    .unwrap()
                    .1
            ))
        )
    );
}

#[test]
fn verify_header_works_valset_rotation_before_delay_period_testnet() {
    // 55474112
    let source = deser_header(
        r#"{"parentHash":"0x4ac159608683e1d62cd3c46e54dfcb058e6caf1a3eb1ca33d6b5737da765198e","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea","stateRoot":"0x8b1b1774811feccce4e55db210aac5bdcc1c0afc565db95a5bba7da1c5aa62c2","transactionsRoot":"0xffac28f838083beaf336f894fdb4292601eba3544c5d21cc5a5eb59bb2692628","receiptsRoot":"0x9ff97855e051eeee9ee1eb49efd5ab2ba52bf46d48500a57fff9fc6224bc6f75","logsBloom":"0x00000000000000000000104000002000000000000000000000000200000000000000108000000000000000000000000000000000000000000000000000200000000000000080000500000008100000002010000000000000000000000000000200080030000200000000000001000400080000008000000000000010000000000000080000000000000000000002000000000400000000008000001000000020020000000000002008000000020000000000000000000000000000000000000000000002000000000000100000000000000000000100001000104002000000008010000000000000010000040000010000008000008200004000000000001000","difficulty":"0x2","number":"0x34e77c0","gasLimit":"0x5f5e100","gasUsed":"0x51b50","timestamp":"0x685583f3","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b277b860a965d83592e741017209605a62eeb83f6ddec5ab918145d730023d7bd94ff5569c13965f9295b3a88d1be544e627c4030f67d6d3b6ca5b44c933d5fe67ef814f94d7f1671f30e64b3362e70d7014a6a2af6bddc233770ed91870fbe8091c7eeef84c84034e77bea0cd0ba3b6896eac74af8b382680a3f8513d8e0395f3cf5c8d5cf172c91a367eaa84034e77bfa04ac159608683e1d62cd3c46e54dfcb058e6caf1a3eb1ca33d6b5737da765198e8005aadb5aa8e1d22c5e2279f90347b7eb57e993ffeca1213edfa29bea4626586b041b35319b05e1e454beff424afe0c774f0633a6d11d879dc2494b0c7224162500","mixHash":"0x00000000000000000000000000000000000000000000000000000000000000fa","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let target = deser_header(
        r#"{"parentHash":"0xb6c3fb5db2749184b29c250dcde3604422b584603a9d8462d051c2e2fc2698e8","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea","stateRoot":"0x26c683b0bfc542c844bd7646f4f30495fd1be51eaf5ca9f94f4f58c63401de23","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x2","number":"0x34e77c1","gasLimit":"0x5f5e100","gasUsed":"0x0","timestamp":"0x685583f4","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb8608c2bd393036be207a5c88df82bcbd5364a5cd024ca42a42e0b16a59c43b3c4834eef510e9fc2f2c84eab6ef0f0cfabf018d26e9d07692c6a63388a3e9d60d80207d79283583d75b718085a8ed3b726165eaef42fe6d324c75cd4ffd82914479af84c84034e77bfa04ac159608683e1d62cd3c46e54dfcb058e6caf1a3eb1ca33d6b5737da765198e84034e77c0a0b6c3fb5db2749184b29c250dcde3604422b584603a9d8462d051c2e2fc2698e880f6d9135f0e16435ab7abad6e3cd91c1e24faa480ba3f865b2430eb9134f9b911735880a79968d5d767d461220f36353945056384cdd430ff75bf3620467ae35000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let attestation = deser_header(
        r#"{"parentHash":"0x6ec704e1a87d58d218103f31256e13016a513fc5ff844163d9477ed5829958b6","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea","stateRoot":"0xdde121b931a529aa48595ca75ed3ca17f34a2eb7a18596ca2fd61980277b6da5","transactionsRoot":"0xaac61e88bd2f9108b22265ff0d314568a50b7cca9ff9eaed252a61a92414cad3","receiptsRoot":"0x700cc891041dc16782667ad7efae9adbc244f59a4dc21141fefc05d8a8b94eca","logsBloom":"0x0004000000000400000000400000320008000000000000000000020000000000000010800000000000000000000000000000004000000000000000000020000000000000018000010000000810000000201000000000000000000000000000020008002002020000000000000100080008000000000000000000001000000000000008200000000004000000200200000000040000000008800000002000002002000000000000200800000002000000000004000200000000000000000000000000000200000000000010000000000000000000000000100010400200002000001000000000000001004004000001000000800000800000c000000800001000","difficulty":"0x2","number":"0x34e77c2","gasLimit":"0x5f5e100","gasUsed":"0xa0520","timestamp":"0x685583f4","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb860ac267d3f027905b02d1c0a6b28861c1f3ebce3229210e85dc7589f52891d44130f6530271d38aebe921ccc8daf46da400f0174c20ac07c6b00f734708a4ba1176754104a96d83228c766175e672717dca352aa4e6e79bed137389fd150f88daaf84c84034e77c0a0b6c3fb5db2749184b29c250dcde3604422b584603a9d8462d051c2e2fc2698e884034e77c1a06ec704e1a87d58d218103f31256e13016a513fc5ff844163d9477ed5829958b6806bf889d7fd07d18228692ba65cab19ce7fc112aa8d8d601768aca194b812f3c509f455e7817fa5cb4debc56deb1c06ccc59b644feeb3e69fa4813235f7fe420c01","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x40000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    let (_, valset) = parse_epoch_rotation_header_extra_data(&hex!("d883010510846765746888676f312e32332e39856c696e7578000000384690280708265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10f8b27fb860939558d8be3f3db29729a2ec0ba2d48ef9be23254980cb49c561d42ba58b4d727a3b4dd69a8df174a876f3ca799f61b60cd66d5dbec0b0c0be4ca3ff0d6e260234fec1b9f6c81f60a2da93831ef39f17230c017daa2cb815bbc2ba5fa84efe2cf84c84034e774ea064fb026e8f5c04e2a642ea5af194bc76961f0c26100fc04e6fe4216e02c867df84034e774fa07ed29e8be587d0d8de91070d0d9d22be22d6b385aa8e5c723e1510526441a5c880dffc3da994d38fe40d51cc4322cd0afe05ae676299b44af2fb2836c41e983baf3cda8ccd4e49392772dfe698f3aaf9a84e2ddd62a81d251784384770feaaa6b501")).unwrap();

    let chain = [source.clone(), target, attestation];
    let res = verify_header(
        &chain,
        Duration::from_secs(604800),
        55474000,
        BlstContext {
            current_timestamp: Timestamp::from_nanos(1750435993000000000),
            epoch_valsets: [(55474000, valset)].into_iter().collect(),
        },
    )
    .unwrap();

    assert_eq!(res, (&source, None));
}

#[test]
fn verify_header_works_valset_rotation_after_delay_period_testnet() {
    // 55474112
    let source = deser_header(
        r#"{"parentHash":"0xb6c3fb5db2749184b29c250dcde3604422b584603a9d8462d051c2e2fc2698e8","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea","stateRoot":"0x26c683b0bfc542c844bd7646f4f30495fd1be51eaf5ca9f94f4f58c63401de23","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x2","number":"0x34e77c1","gasLimit":"0x5f5e100","gasUsed":"0x0","timestamp":"0x685583f4","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb8608c2bd393036be207a5c88df82bcbd5364a5cd024ca42a42e0b16a59c43b3c4834eef510e9fc2f2c84eab6ef0f0cfabf018d26e9d07692c6a63388a3e9d60d80207d79283583d75b718085a8ed3b726165eaef42fe6d324c75cd4ffd82914479af84c84034e77bfa04ac159608683e1d62cd3c46e54dfcb058e6caf1a3eb1ca33d6b5737da765198e84034e77c0a0b6c3fb5db2749184b29c250dcde3604422b584603a9d8462d051c2e2fc2698e880f6d9135f0e16435ab7abad6e3cd91c1e24faa480ba3f865b2430eb9134f9b911735880a79968d5d767d461220f36353945056384cdd430ff75bf3620467ae35000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let target = deser_header(
        r#"{"parentHash":"0x6ec704e1a87d58d218103f31256e13016a513fc5ff844163d9477ed5829958b6","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea","stateRoot":"0xdde121b931a529aa48595ca75ed3ca17f34a2eb7a18596ca2fd61980277b6da5","transactionsRoot":"0xaac61e88bd2f9108b22265ff0d314568a50b7cca9ff9eaed252a61a92414cad3","receiptsRoot":"0x700cc891041dc16782667ad7efae9adbc244f59a4dc21141fefc05d8a8b94eca","logsBloom":"0x0004000000000400000000400000320008000000000000000000020000000000000010800000000000000000000000000000004000000000000000000020000000000000018000010000000810000000201000000000000000000000000000020008002002020000000000000100080008000000000000000000001000000000000008200000000004000000200200000000040000000008800000002000002002000000000000200800000002000000000004000200000000000000000000000000000200000000000010000000000000000000000000100010400200002000001000000000000001004004000001000000800000800000c000000800001000","difficulty":"0x2","number":"0x34e77c2","gasLimit":"0x5f5e100","gasUsed":"0xa0520","timestamp":"0x685583f4","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb860ac267d3f027905b02d1c0a6b28861c1f3ebce3229210e85dc7589f52891d44130f6530271d38aebe921ccc8daf46da400f0174c20ac07c6b00f734708a4ba1176754104a96d83228c766175e672717dca352aa4e6e79bed137389fd150f88daaf84c84034e77c0a0b6c3fb5db2749184b29c250dcde3604422b584603a9d8462d051c2e2fc2698e884034e77c1a06ec704e1a87d58d218103f31256e13016a513fc5ff844163d9477ed5829958b6806bf889d7fd07d18228692ba65cab19ce7fc112aa8d8d601768aca194b812f3c509f455e7817fa5cb4debc56deb1c06ccc59b644feeb3e69fa4813235f7fe420c01","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x40000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let attestation = deser_header(
        r#"{"parentHash":"0x3fdd6eb1e12e042bb06250423c472e8edd996c830b8e91a5e53f7eda03aa9405","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea","stateRoot":"0x166fbf66c503377536a8d56826bee5f27c1a7f12901518c614807155fdb72933","transactionsRoot":"0xf32c0923c016612b60094495958bc70d4800b32c9c88c43d85b62c1ac3548e90","receiptsRoot":"0x895100f4586b6e3eb4776d3ea3cd6dd2ae594ecd6eee63b29e652d031ca0ea37","logsBloom":"0x0000000000008400000004400000200008000000020000000000000000000000040014800000000200000000000200000000000000000010221000000000000004000000004000010000000c000000002010000000000000000000800000600200080020020200000000000101000800080000000000000000200010000000000004482020000000400000000002000000000400080001008000004000000020080000000000012008000000020000000000100000000000000000002000000000000002001000000000100000000000000000000000041000104003000030000000000000001000010000040000010000008000008080004000000004009000","difficulty":"0x2","number":"0x34e77c3","gasLimit":"0x5f5e100","gasUsed":"0xfd28c","timestamp":"0x685583f5","extraData":"0xd883010510846765746888676f312e32332e39856c696e757800000038469028f8b27fb860a8f61a3fccdd005d088675f23ce095e7491244f0cbd53b28a60ea1533a94dc03c22aa36106bfc4f7555a392e634c6e9d0f0aa5e573e2c6c4ce7a9b66662fbc5b909666d745f554a906af696888f990d92fa6dbf56ba4f9f62b71eef5053660def84c84034e77c1a06ec704e1a87d58d218103f31256e13016a513fc5ff844163d9477ed5829958b684034e77c2a03fdd6eb1e12e042bb06250423c472e8edd996c830b8e91a5e53f7eda03aa9405804a3580d2f84d406cf66d597425e94e93f8cb331947cfacfe3a7d95aa60cc8e437f512a2e95f212e6b19f7b717f58c753984fc5c21facd98fc2f7730406d02f6201","mixHash":"0x00000000000000000000000000000000000000000000000000000000000001f4","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    let (_, valset) = parse_epoch_rotation_header_extra_data(&hex!("d883010510846765746888676f312e32332e39856c696e7578000000384690280708265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10f8b27fb860939558d8be3f3db29729a2ec0ba2d48ef9be23254980cb49c561d42ba58b4d727a3b4dd69a8df174a876f3ca799f61b60cd66d5dbec0b0c0be4ca3ff0d6e260234fec1b9f6c81f60a2da93831ef39f17230c017daa2cb815bbc2ba5fa84efe2cf84c84034e774ea064fb026e8f5c04e2a642ea5af194bc76961f0c26100fc04e6fe4216e02c867df84034e774fa07ed29e8be587d0d8de91070d0d9d22be22d6b385aa8e5c723e1510526441a5c880dffc3da994d38fe40d51cc4322cd0afe05ae676299b44af2fb2836c41e983baf3cda8ccd4e49392772dfe698f3aaf9a84e2ddd62a81d251784384770feaaa6b501")).unwrap();

    let chain = [source.clone(), target, attestation];
    let res = verify_header(
        &chain,
        Duration::from_secs(604800),
        55474000,
        BlstContext {
            current_timestamp: Timestamp::from_nanos(1750435993000000000),
            epoch_valsets: [(55474000, valset)].into_iter().collect(),
        },
    )
    .unwrap();

    assert_eq!(res, (&source, None));
}

#[test]
fn verify_header_works_longer_chain() {
    let ancestor_2 = deser_header(
        r#"{"parentHash":"0x1170288aea0ccaf01a06549f12d93702c21371d0fdfa0f8de38619fc3c30466c","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x58567f7a51a58708c8b40ec592a38ba64c0697de","stateRoot":"0x43591edc11a50aa362796276e885f793273326788e4a0cb90415eba45027b9be","transactionsRoot":"0xc0b2f8fdc216a10dcce5fd9a3521949a4f5781338820309ff72ba366dcbb2eda","receiptsRoot":"0xad40bdc91ae8761f18e355bd7acc3a5f145f4bb1fc0fffafbcc1e4c96071bcad","logsBloom":"0x1825b604686ad030bb0114448241100017d01c0284402280248e80112e6541a18400158bf0008040320648812892810dc3c1c9926d047d01d6a2034430220091ed0094970740656887012f28e04981f4bc1908c3604a082d70e61004a6890839560c6820868202c00310840526043a611808044a8b05ce420200c030048c02b381c0408c7c38138bb5b1ac83140047944c348ca14c216a0800080040e3070420030510190198216d4b2629520a094664c6a3124568a14e08027b2136304841230c9017066a04840b8bc41b39a43b13206402038202881c902cb0e04a49a0e91408102c198a165b5003615504800665610042b01020900d61448ca320229a2814","difficulty":"0x2","number":"0x354d461","gasLimit":"0x47868c0","gasUsed":"0x7e90a1","timestamp":"0x688aa38c","extraData":"0xd883010511846765746888676f312e32332e30856c696e7578000000098d24acf8b5831effffb86099128ea116a3fb0916efdaf6f4242dc66e5cad04b80afa7f37a55aada7409a5eca666d42c4bdade25963a2cd26b8318509ff565114afd0ea036e1c892fe2fbea667e0913fabb36acbe2d8848aad2bcff90f24f532b7a5ff7803a687d69ce6363f84c840354d45fa05cf48713a692239fd2388cde813b87ba594d97a181f6887ef470f84805f3885e840354d460a01170288aea0ccaf01a06549f12d93702c21371d0fdfa0f8de38619fc3c30466c8049396526c50acfa017133522c8a4b553c3ded82262e49e529e33dab86e8d74f61da6bd3433a466a903bbdf4411497ace029b86eb9905f2b9a68a0b6286a8a80601","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x20000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let ancestor_1 = deser_header(
        r#"{"parentHash":"0x88260bcc069b4a5875376f34001c2474d5b00d9439601ce978b0c30c5c8c3568","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x58567f7a51a58708c8b40ec592a38ba64c0697de","stateRoot":"0x50c79b38c64362261e28b56c1302e22c5ddfce06ef44bfe0d1662635ddc62e58","transactionsRoot":"0xc8825e793aef239be7d2908edfeaa7e3bff875d5b7cc733a5a9c21b17118dda3","receiptsRoot":"0x6325ba168be9f01433c2df496058a81117204d8aca245ee5a9046a93df361df2","logsBloom":"0x1c2246018723199482210465d32101421c38b88230800a80a6c8090225b0948b1c08d0483c0600002a8042110a1300098109d010a05436408e62022080a242b28400101414608928a710a458806580a524900811820e8b0453941415810100224e1d206156f6184206000e9cc1d00c69088804033206c8030603c071346e2681811048e005081104b0a0ad0c14000d901934ac491110430802000150418c45e2023404056069243008a421800a000241044921400211280a8a0b2811a40040230a40050a41000401aac401020005200660a407dea2414450ae3a40a20544e80c0c5218911a5c502005c01024c02005710ac0aae020c225494c20610002c20420","difficulty":"0x2","number":"0x354d462","gasLimit":"0x47868c0","gasUsed":"0x7d0248","timestamp":"0x688aa38d","extraData":"0xd883010511846765746888676f312e32332e30856c696e7578000000098d24acf8b5831effffb860853afd00b59aec31853b4e210bc477d6c6efa1db7030501c51d7c98f3a42057ad3d935cdf3ac47dceace931d0605fab901e300dfc877daba4b181317aef744bcfac52e80068ec16f1c64af3ded468e47e83dc916516f30e16d12be90cdb206f9f84c840354d460a01170288aea0ccaf01a06549f12d93702c21371d0fdfa0f8de38619fc3c30466c840354d461a088260bcc069b4a5875376f34001c2474d5b00d9439601ce978b0c30c5c8c356880611bf160cbecb642b4785b58d46965e424b0bf6ef88266df56273912cd3505aa40d3872f5d13a62c8c074b168a1207c92322c9aa91fe431fe5a21494ccd315d200","mixHash":"0x00000000000000000000000000000000000000000000000000000000000001f4","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let source = deser_header(
        r#"{"parentHash":"0xbbbc1df0f9be91a8e8b9290f54f5919366df67531b930558bf8ddfee69a4cd59","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x58567f7a51a58708c8b40ec592a38ba64c0697de","stateRoot":"0xa4501e92479912034871fad648445d33aabaa3a7e0fc8c8ecfe74ace5acae9e4","transactionsRoot":"0x50a010d3efe577d48a2a635ff2d8792b156164d96344639936746cf631898072","receiptsRoot":"0xabcb93feaab52e5d9ab437d5a00ce38d30745788a343ec656a527b8e41dea2f1","logsBloom":"0x0020800202202060c6c535548212a0dc101088c82800c220298283a12628b181d9c1101219049000251210000e834182c346c1806c00350506020280002c808014401105074001680714899802a58124a4580c6701400946b39c00ca02420102c70e0132a6f30a580e0414214c92f8040824a4546001a48621605051a4482b8903c0402402084954a0800408bd004590a0b414040100421a23008a494305162e02140409616023ea6ba4115202654055088022c00000c00046422030240010310020050ac804060884c0083530290047618002280be10415203860c20c32e801181005000002530801101004002123410042b5ad288c1808e120222200880844","difficulty":"0x2","number":"0x354d463","gasLimit":"0x47868c0","gasUsed":"0x7aa72f","timestamp":"0x688aa38e","extraData":"0xd883010511846765746888676f312e32332e30856c696e7578000000098d24acf8b5831effffb86096e62c44748853708a937444164482f4b60ce09f30fca094e9b092eab2e44210a04f16d286fa3aa8575414461245a0a60fae8e7fd01d03aa91f0f2da060eaf0ca81d97d5ecbe76e97e40d30c91a5c1bad2d3a1145691fa924a0d40e5d6aac7b4f84c840354d461a088260bcc069b4a5875376f34001c2474d5b00d9439601ce978b0c30c5c8c3568840354d462a0bbbc1df0f9be91a8e8b9290f54f5919366df67531b930558bf8ddfee69a4cd5980b647eb70554345c38b8b89f3e907b5510f892c65e03aaa625734802af0f120ac69dea4165cc144b0907cc51b5081c41dea1742bba047bc77a5c76fa44fcd87d101","mixHash":"0x00000000000000000000000000000000000000000000000000000000000000fa","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let target = deser_header(
        r#"{"parentHash":"0xb36529273fcf52424f5d80a0ed48c901bdad22a19a98c5219e4601b293a6ff9d","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x58567f7a51a58708c8b40ec592a38ba64c0697de","stateRoot":"0xa3237463239b5e577bfc61437eba924b8ba9f2ff8ff6a18fb0df46fa171a2435","transactionsRoot":"0xdfeb85689de1f52c3acbe8570a6c9dc309c234aa2678421a300b5b0750153819","receiptsRoot":"0xb9bcdee4a569cf33df272e8809c127cbf72cb7d72b6c139e611bbd82b7392fa9","logsBloom":"0x28208300002224008a20544480318041154030021014008067a9b4a025020190060010130000200022335400268e80100341a0020208b401040287201022a89004000405944080a803000508884002242c111800001881000004040100920020440c3120034220608c02004064512c00094004310805e20480906010040802c1887060e040080108c08882083c00c480083426242000c00890980140018006a0860400080800162928322142022480500400204001810a84c30820052008026d8e40030648002808a0800190130423026480066296080010613040029840e800101010130003500021401004c80001408a0ca205088000014821292136c04444","difficulty":"0x2","number":"0x354d464","gasLimit":"0x47868c0","gasUsed":"0x5a346c","timestamp":"0x688aa38f","extraData":"0xd883010511846765746888676f312e32332e30856c696e7578000000098d24acf8b5831effffb860a2bf52e80cb296ba50426ea8e45cb4bd5c6c41025730577688c8ae0b898a916f7f5415bf258834b5dfe93160cd3c508b0582045a1c7e59e0dba50338178d8f2dba8535e4437c645cb1529459b339697d3614bb7b6f7edace97f0faedafede096f84c840354d462a0bbbc1df0f9be91a8e8b9290f54f5919366df67531b930558bf8ddfee69a4cd59840354d463a0b36529273fcf52424f5d80a0ed48c901bdad22a19a98c5219e4601b293a6ff9d80d12d92849c23643f5d82ace637f6d62a5c700d1241ad64597ddafe49c6a52cb5395e69da3f78e820777415dd1c2577a15beae575e63e4a776d082c2c6818647b00","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let attestation = deser_header(
        r#"{"parentHash":"0x6d62a2094fdd7791e5a3fb0f5eca8a1d01d8b328735e11f7290bd5fb9f8b10a6","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x58567f7a51a58708c8b40ec592a38ba64c0697de","stateRoot":"0x9a4e94c3d513c00170907ca318a349f90ee9b3d3ec96d8f4cf750c872ac19c59","transactionsRoot":"0x43dbf881c8c95a0e5a17313083a07241dc339f3b75b4e72d43980be3688a2cb1","receiptsRoot":"0x9ee7fbb03006b7ebdc1d14cacb0552ad46fcc8e55dcfb4f96ac708373050b694","logsBloom":"0x00283ae9002a4c41e3851d44de82c040b004800e012160c0a390690020101083964234009000060102a00828ae76a009a1248861548e3e90160b0b1840bc06b20400244c0768a4292b524109900d0c657650c8298426098602040f02808544204c4e1172c04a1cc70883e0d68424810408802615d84400d00001d490462896d50194e080985e0c03d8a8090296440592503485096140420ca04c014c29262521564629081805003128660e11022e4041712006700002090c8a632030344429c18081112ad0400049e180088113240c0061013a42028246d0273253030516c0031610ea0202145604872a9286186181708a00b1280088047542b1274102908c08","difficulty":"0x2","number":"0x354d465","gasLimit":"0x47868c0","gasUsed":"0x88af58","timestamp":"0x688aa38f","extraData":"0xd883010511846765746888676f312e32332e30856c696e7578000000098d24acf8b5831effffb860a61fcb0997710b63772e03cf78f1726c041ba93d9b332a81999e3abbbbfe7b1ee74cc4a56586ea48e6db310dc0e3d97715dd3232563c68a6b1b3495534a726e363003dcb1ee25caa2fc3f62a5a96e52889a4185dfb6013e38f99b207d475020af84c840354d463a0b36529273fcf52424f5d80a0ed48c901bdad22a19a98c5219e4601b293a6ff9d840354d464a06d62a2094fdd7791e5a3fb0f5eca8a1d01d8b328735e11f7290bd5fb9f8b10a68069e82d218f74ed2e4da7c8d50eb39f258b010200a999733a898bcddbed6c115765b1637f4408bae963dda789ad75ed8b7de9591b0c4f9c9477df1e8fbdc4c2c601","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x20000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    let (_, valset) = parse_epoch_rotation_header_extra_data(&hex!("d983010511846765746889676f312e32332e3130856c696e75780000098d24ac15286c1b674d48cff67b4096b6c1dc22e769581e91a2783aa7911798eb2b7e5a3c61832f65731e14789cf1d624de2c83535d7719b466cdb2057beff302eab6c3cbfb42ee2337e9627a91dd13e453246856d58797ad6583d762abd04e3688a7c071dbc7eb3d0ace1c06baf163fdc8ffc742fec16f09fa468d30778a3c533b944899d33ae3225a3aee0738944092685a336cb6b9ea58836436709a2adc89afc1c041d36ee43ed51b1cb17b9dff14068e594b79a3c401a0bcf9fae9fd86324822fc0bb768f0b7dae76927b23d3954460a252b4feefa821d3351731220627d7b7d1f3db3e34a6e7967c4da80dd3e5227acb02c92f33a026bbce5e52c19b7d8746b7e55d3e29b9083de0bf334fdf8ac91bc14854d15d9bcd0c2f33e7510c0de8b42697ca558234a8a81ab85d1ea9d9842484aca571512a78ed805c2398ce055d90fa0327b1467d45a00ddc183798193b50fcb15352095e14e5acf9684652bea56f2f01b7101a225ee33d23f8bcfeba8fcafdc6b6f9016d5a0dd08e4685a13bffd8c2087f66bf7ca2dace7fbbc40c40824e30a84d3fe62a2ddcd52175009317fd4f6f8feea9dae41e5f0a4737bb7a7d5b3a0de43e5a979f8d7a9ad04f8f3f102bdbb17ef0bf6ac9a8fce3f110f409d99828be80295da56c2c7a7becd3647ce40502aecfe253e6aa0e8d2a06e12438ffed0fe16a0b15df58914a6b751909f0558a9f9af8efca7d46e480fc24478d977dafe7daf5161b38c72e9e1ea4865c288ef5b8054ab58567f7a51a58708c8b40ec592a38ba64c0697de8d78def84b10ab93dbfff6980d1054a2bc561bcf0abf3daf6096849bf03744fd4a49392e4813dc2251d68f6f95f27ba75adde0151bfab27f329e5112c1aedeed7f0d3692b6267282cb29f87af27f03e67f499239c6eaed428a93265e4ac7977f3c5d76792ed777809439dd24618c805859ddcead75b851a27d7101438f45fce31816501193239a83ad9a5f4ae5ec7dd886b09a47021461ec6f1971b3558f31e622311e94714398c80573fd531e0e8b4c4c3b456c4a5b9bf67b501c7944185130dd4ad73293e8aa84effdcee7b7adb10448b8be5fc875af7df065a5ee57f2ace2cca77b37bbe2e30fd16481afe8a64fe4dd3aff03d14fb180a05bf6a08a239732871adc8829ea2f47e94087c5fbad47b6adc9ae11a5f0da15082a4ded8abaeb73338984c06e2c1af2eb24232e00511e95b24e89291d689f6bedb13d5a398af2ec9bb56c2b4dbe5a06d79911c9899b6f817696acfc90ba8c56b1a3c032a3a0395d0f42f3a00b4f50ce9dc41f819a601e8f17b00e7a4eba8a9af4c4b3fdd31d555ccf70058d9f1b7fae54be07f4fee34eb1aacb39a1f7b6fc92abfb714bc2daced46244ccab91917be3d8271a995636b24aa44ff97e3033f41262b2dad5ce2b31734e4dd3912c5838eeb4647b856cb9c3856d559c885bed8b43e0846a47a663982486c84b2f66d9391efe6875d30be1d907e55d9c4a5a224de92a5d8ff180cc4ebca44253fa5a9730cc89d61994ca503a7ed99eca485da2e875aedf7758472c378c91dce99bbdc44ee9500ed1e5c864bc88ba518585c7e6de5e94d26ee216dd8a5e06c5d2fc740123976c9588787b54998cccb42a9b8d6c46468900527bc741938e78ab4577b1e211be938b9f77888cbdc7bd3787148a6d1653eb0e17603df69d67db30fa4857e11edec461e01e3e02cea2c7d2c5ddd3b0d838ccceae7ebf1781d11d1bb741db7fe1a7b39bdc22b7275d8456ee325424d33829d364270b1ecebb389318c7f0cb1f1c334f05d1d5e26472f2cd07f5d8025ea266f8b99643fafc79d9404de68e48c4d49a3936f7878d68efc0951aa89bf89fd829dd021fac27712f0f046e70d2d33a8a1fc05554a16d26669a9adb33bb41aaff43df7d4da0f8de5e61322302b2c6e0a525cc842f10332811bf8e69853df9edb142b5d596f93bfa14253a733cb9d2d5a7ed1fc345e248a8cae7f23f438930123eebf61c98785d846a8b10f8b5831effffb860b61ca24c5f35b257db419df0f2719990d255e19ec6fae6253b911a98488c7e231a43c8f9e394946704fd3cafcc3c77990d983873dde5352a92c91032a1f39751c1df71a1548b292fe7f9dbce9f644287dc3fb067a2a4b38e4dfaa9d1c1d310eef84c840354d04ea0011a2099476f08eee431facc78722641f4930084fc60ac50b6d937e0091d889d840354d04fa090f6d83558e72d73dd35c5272d5eff80431a02cc5ede27599c8bae4b84183a4d80e1d8ff70991b6020f0333e68f88b0fd448ebbe5292721d90b10dbfd96ef3068f331c5935f212182abb22ac46f333296681495a5f445039ac5694bf72b6423c3000")).unwrap();

    let ctx = BlstContext {
        current_timestamp: Timestamp::from_nanos(1753916740000000000),
        epoch_valsets: [(55890000, valset)].into_iter().collect(),
    };

    let chain = [source.clone(), target.clone(), attestation.clone()];
    let res = verify_header(&chain, Duration::from_secs(604800), 55890000, ctx.clone()).unwrap();

    assert_eq!(res, (&source, None));

    let chain = [
        ancestor_1.clone(),
        source.clone(),
        target.clone(),
        attestation.clone(),
    ];
    let res = verify_header(&chain, Duration::from_secs(604800), 55890000, ctx.clone()).unwrap();

    assert_eq!(res, (&ancestor_1, None));

    let chain = [
        ancestor_2.clone(),
        ancestor_1.clone(),
        source.clone(),
        target.clone(),
        attestation.clone(),
    ];
    let res = verify_header(&chain, Duration::from_secs(604800), 55890000, ctx.clone()).unwrap();

    assert_eq!(res, (&ancestor_2, None));

    let chain = [
        ancestor_2.clone(),
        source.clone(),
        target.clone(),
        attestation.clone(),
    ];
    let res =
        verify_header(&chain, Duration::from_secs(604800), 55890000, ctx.clone()).unwrap_err();

    assert!(matches!(res, Error::InvalidChain));

    let chain = [ancestor_2, target, attestation];
    let res = verify_header(&chain, Duration::from_secs(604800), 55890000, ctx).unwrap_err();

    assert!(matches!(res, Error::InvalidChain));
}

#[test]
fn calculate_signing_valset_epoch_block_number_works() {
    let cases: &[(u64, u64)] = &[(50932064, 50931000), (50932065, 50932000)];

    for &(h, expected) in cases {
        assert_eq!(calculate_signing_valset_epoch_block_number(h, 7), expected);
    }
}

#[test]
fn header_hash() {
    let header = deser_header(
        r#"{"withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","parentHash":"0x456e27b4d951b8503078f5fa44d20f8d2ce976f4424a9c45782b73658c856d50","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x8a239732871adc8829ea2f47e94087c5fbad47b6","stateRoot":"0x2f3a8a8a47bc02231865163b9cc539e67a10e97bf8acc30279f2649f7c21cc85","transactionsRoot":"0x99f7054aa082decd3ac39e0a8d9189ec4d1d91fe953b2ada2cce29ec3a5715e6","receiptsRoot":"0x903944bf3a03f3933949bf9355dc73be8be02dfbf86d4066a1b6e41f0251346f","logsBloom":"0x05b1561781c6205dcea13c5b96cb1a801fd0b40a1e1b6ba42f80e21636949a9db102798b165f02212689f5202c8a83818904b22014dc6085068aa319552805d1fc0adf0c13684c3c43946d4cb63b9e24b490cabb336ac12e201500d0da2b9e68c3db07217846b842edec4337d71679a70d82841746856c0047acc8dda2a9a3db9084cd223a5c7a4889883b96bd4087f3e87eec65b19be169028280e18306572062ec04c9032e97a1ab0e3371c6644771d3aa36c0408e090d09dfb1a9e1ab9899b869e1ae4dc080a1aab47198c11acb09f1889d333ba42e983072dc73b404c8010ad30b178da4481309f5a28d926781c11491f7a0684b357b71ee177fb2c16721","difficulty":"0x2","number":"0x30a4c62","gasLimit":"0x7735940","gasUsed":"0x18fe8b7","timestamp":"0x68437ede","extraData":"0xd88301050c846765746888676f312e32332e37856c696e75780000003bfc8c16f8b5831f7fffb860906c1bdcc84b3cfbbab0f3df2939413a36c373e351fe7ec6654cf983b8d6ae80f052d2a66bddcf7bf6f4c28754c4dc770e68597fba67ee38748639c31083ed517ccaae5836e421d4b0ba0234173b456646d8146f0063846eb660e1fdcf91f3baf84c84030a4c60a0db7cefa3c1fe375262865b93e4d4223b045da94df8fd769875fb5fc7f73056da84030a4c61a0456e27b4d951b8503078f5fa44d20f8d2ce976f4424a9c45782b73658c856d508003ce6d018ef27172e9d39c346aa0dc3a939a4cc3766078b54311526b987d418332d87369564cf5421fd122417e61369bff2c85e967e2ce875936ef1cd57b321d01","mixHash":"0x00000000000000000000000000000000000000000000000000000000000001f4","nonce":"0x0000000000000000","baseFeePerGas":"0x0","blobGasUsed":"0x40000","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    assert_eq!(
        header.hash(),
        <H256>::new(hex!(
            "20315dee443b8910db5041505a17758cc44ac2348af003a08760f9a14995f3ae"
        ))
    );
}

#[test]
fn parse_extra_data() {
    let ed = hex!(
        "d883010510846765746888676f312e32332e30856c696e7578000000384690280808265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5a7dee0bcaeb78849ec4ad4e2f48688d2e9f2315b848ffc9a3fac00d9fbaebcb63f2b7c0a4747d9ffecd4b484073ad03d91584cb51af29870c1c8421b757f4f6fae813288d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10f8b381bfb860ae6634e5acd76e7080d2127434089bb9f3c9681af4200214fe77fd3101d34d4ba93876f48cf14a636cf534f235971c990d5ca89f766247a68e4c87637b9ce6ea93ffdffff39ca3c9b60993043ee454aa963506ec59b18fc69df6fea0036df2c6f84c84038707c6a0d78afbd6baa5e47a630891b88025074d2cfad6fc4507265403f3ce157145c85584038707c7a0e9a269318d025f9fcfdcb1449109c73e9f4530bce6f4c94b0af87401d16f486c8012cfe946eff7de7e23b6cae30d710a945a406439dca3e18eea9014f71393e0ec31fd47c133486e72b693ad17663afa8cd1fe3e5e723b582d06cec8a5bb820dfa01"
    );

    let res = parse_epoch_rotation_header_extra_data(&ed).unwrap();

    let vote_attestation = VoteAttestation {
        vote_address_set: ValidatorsBitSet::new(
            0b00000000000000000000000000000000000000000000000000000010111111,
        ),
        agg_signature: hex!("ae6634e5acd76e7080d2127434089bb9f3c9681af4200214fe77fd3101d34d4ba93876f48cf14a636cf534f235971c990d5ca89f766247a68e4c87637b9ce6ea93ffdffff39ca3c9b60993043ee454aa963506ec59b18fc69df6fea0036df2c6").into(),
        data: VoteData {
            source_number: 59180998,
            source_hash: hex!("d78afbd6baa5e47a630891b88025074d2cfad6fc4507265403f3ce157145c855").into(),
            target_number: 59180999,
            target_hash: hex!("e9a269318d025f9fcfdcb1449109c73e9f4530bce6f4c94b0af87401d16f486c").into(),
        },
        extra: Bytes::default(),
    };

    let valset = Valset::new(
        vec![
            (
                hex!("08265da01e1a65d62b903c7b34c08cb389bf3d99").into(),
                hex!("96f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c2").into(),
            ),
            (
                hex!("1a3d9d7a717d64e6088ac937d5aacdd3e20ca963").into(),
                hex!("979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd998500230").into(),
            ),
            (
                hex!("53387f3321fd69d1e030bb921230dfb188826aff").into(),
                hex!("aa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b").into(),
            ),
            (
                hex!("76d76ee8823de52a1a431884c2ca930c5e72bff3").into(),
                hex!("803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf").into(),
            ),
            (
                hex!("7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea").into(),
                hex!("99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf").into(),
            ),
            (
                hex!("90409f56966b5da954166eb005cb1a8790430ba1").into(),
                hex!("962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5").into(),
            ),
            (
                hex!("a7dee0bcaeb78849ec4ad4e2f48688d2e9f2315b").into(),
                hex!("848ffc9a3fac00d9fbaebcb63f2b7c0a4747d9ffecd4b484073ad03d91584cb51af29870c1c8421b757f4f6fae813288").into(),
            ),
            (
                hex!("d447b49cd040d20bc21e49ffea6487f5638e4346").into(),
                hex!("ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb").into(),
            ),
        ],
    );

    assert_eq!(res, (Some(vote_attestation), valset));
}

#[test]
fn parse_epoch_rotation_header_extra_data_no_vote_attestation() {
    // https://testnet.bscscan.com/block/59180000
    let ed = hex!(
        "d983010511846765746889676f312e32332e3130856c696e75780000384690280808265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21a3d9d7a717d64e6088ac937d5aacdd3e20ca963979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd99850023053387f3321fd69d1e030bb921230dfb188826affaa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf90409f56966b5da954166eb005cb1a8790430ba1962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5a7dee0bcaeb78849ec4ad4e2f48688d2e9f2315b848ffc9a3fac00d9fbaebcb63f2b7c0a4747d9ffecd4b484073ad03d91584cb51af29870c1c8421b757f4f6fae813288d447b49cd040d20bc21e49ffea6487f5638e4346ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb10c13d0223d7bf9e62be37d4bf9ab5279edc2669a9e061e2e68394010d23d590375f9d6e0eaea5d90e25a937692e400540ed45f4373eb1df4ae5297d980f8604f301"
    );

    let res = parse_epoch_rotation_header_extra_data(&ed).unwrap();

    let valset = Valset::new(
        vec![
            (
                hex!("08265da01e1a65d62b903c7b34c08cb389bf3d99").into(),
                hex!("96f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c2").into(),
            ),
            (
                hex!("1a3d9d7a717d64e6088ac937d5aacdd3e20ca963").into(),
                hex!("979974cd8ff90cbf097023dc8c448245ceff671e965d57d82eaf9be91478cfa0f24d2993e0c5f43a6c5a4cd998500230").into(),
            ),
            (
                hex!("53387f3321fd69d1e030bb921230dfb188826aff").into(),
                hex!("aa39ebf1c38b190851e4db0588a3e90142c5299041fb8a0db3bb9a1fa4bdf0dae84ca37ee12a6b8c26caab775f0e007b").into(),
            ),
            (
                hex!("76d76ee8823de52a1a431884c2ca930c5e72bff3").into(),
                hex!("803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf").into(),
            ),
            (
                hex!("7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea").into(),
                hex!("99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf").into(),
            ),
            (
                hex!("90409f56966b5da954166eb005cb1a8790430ba1").into(),
                hex!("962a2342bac4831c6de73fcb77ad08669aaaa0a2ba6c6973a02b8928dbe573d17864e48c3521f238ace1c16e160bb7f5").into(),
            ),
            (
                hex!("a7dee0bcaeb78849ec4ad4e2f48688d2e9f2315b").into(),
                hex!("848ffc9a3fac00d9fbaebcb63f2b7c0a4747d9ffecd4b484073ad03d91584cb51af29870c1c8421b757f4f6fae813288").into(),
            ),
            (
                hex!("d447b49cd040d20bc21e49ffea6487f5638e4346").into(),
                hex!("ad9fc6d1ec30e28016d3892b51a7898bd354cfe78643453fd3868410da412de7f2883180d0a2840111ad2e043fa403eb").into(),
            ),
        ],
    );

    assert_eq!(res, (None::<VoteAttestation>, valset));
}

#[test]
fn missed_fast_finality_attestation_for_epoch_rotation_block() {
    let ancestor_66277000 = deser_header(
        r#"{"parentHash":"0x2376d907682c40c631a5fc7841326c3834318ec32ca2ba38072b8e440415f6fd","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0xf9814d93b4d904aaa855cbd4266d6eb0ec1aa478","stateRoot":"0x7c26a63708c424001272886820da7ba72e71ac1d96c933202a9091a7fb589e37","transactionsRoot":"0x4a40a9fc88b011dbdfa1be91225f3d2375b77024551089ef620d761ceafd3082","receiptsRoot":"0xb99818e51e68e4147862f8649f69c3178160d5a84c17e5c0ab534e43e41d99b1","logsBloom":"0x12322ac47147084285215344bc061c9256041ac710d1160886c9581427ea41850402d006021ec0125310102d23034080230284ff810821c0450809ce5128e0da84ba860c864088ec23094588b4420320241024b8d2e8a000e3558d20a8280622091c742026228400e1418022a4490e139c4095831cc9668282005058184813c82004661019c24880d0c8812cd5e06581ca760c59e1904088456835606940066802048c49cc010822ecc459430ae1861004a2427a603a58000840420023402ac0e08a1b024003800040ce0180d0d2220562cc5182032850d9e012c0070806b200215802033d7d4c4103f452051000c164d880cc0041841140f8c7380433810d93","difficulty":"0x2","number":"0x3f34e88","gasLimit":"0x5f5e100","gasUsed":"0x6ffa8a","timestamp":"0x69018a4b","extraData":"0xd883010513846765746888676f312e32342e30856c696e7578000000098d24ac150dc5e1cae4d364d0c79c9ae6bddb5da49b10a7d9a19eee71b397e9d88d43477eefdaa457ca7857c20011988042f56bab6ae1f97144d5b9686f3da8bbb0c5ee0858f6af111cfdbd2dff70c6e2e30df5012726f87731f381648e9879d77f0f25c8f6348135cef7477c2455f516bec180921d4c669eae7258857327674ace724b598c0df3fd41068ef837e9627a91dd13e453246856d58797ad6583d762abd04e3688a7c071dbc7eb3d0ace1c06baf163fdc8ffc742fec16f09fa468d30778a3c533b944899d33ae3225a3aee0738944092685a336cb6b9ea58836436709a2adc89afc1c041d36ee43ed51b1cb17b9dff14068e594b79a3c401a0bcf9fae9fd86324822fc0bb768f0b7dae76927b23d3954460a252b4feefa821d3351731220627d7b7d1f3db3e34a6e7967c4da80dd3e5227acb02c92f33a026bbce5e52c19b7d8746b7e55d3e29b9083de0bf334fdf8ac91bc14854e5acf9684652bea56f2f01b7101a225ee33d23f8bcfeba8fcafdc6b6f9016d5a0dd08e4685a13bffd8c2087f66bf7ca2dace7fbbc40c40824e30a84d3fe62a2ddcd52175009317fd4f6f8feea9dae41e5f0a4737bb7a7d5b3a0de43e5a979f8d7a9ad04f8f3f102bdbb17ef0bf6ac9a8fce3f110f409d99828be80295da56c2c7a7becd3647ce40502aecfe253e6aa0e8d2a06e12438ffed0fe16a0b15df58914a6b751909f0558a9f9af8efca7d46e480fc24478d977dafe7daf5161b38c72e9e1ea4865c288ef5b8054ab58567f7a51a58708c8b40ec592a38ba64c0697de8d78def84b10ab93dbfff6980d1054a2bc561bcf0abf3daf6096849bf03744fd4a49392e4813dc2251d68f6f95f27ba775b851a27d7101438f45fce31816501193239a83ad9a5f4ae5ec7dd886b09a47021461ec6f1971b3558f31e622311e94714398c80573fd531e0e8b4c4c3b456c4a5b9bf67b501c7944185130dd4ad73293e8aa84effdcee7b7adb10448b8be5fc875af7df065a5ee57f2ace2cca77b37bbe2e30fd16481afe8a64fe4dd3aff03d14fb180a05bf6a07e1fdf03eb3ac35bf0256694d7fbe6b6d7b3e0c8a066981de27634c2d17a68333f6d9b0c8cd7e08882c397c6ad92d95f8c279d6ef9ea04a1e2f4c4cdfe7ea6015f367ccb8a239732871adc8829ea2f47e94087c5fbad47b6adc9ae11a5f0da15082a4ded8abaeb73338984c06e2c1af2eb24232e00511e95b24e89291d689f6bedb13d5a398af2ec9bb56c2b4dbe5a06d79911c9899b6f817696acfc90ba8c56b1a3c032a3a0395d0f42f3a00b4f50ce9dc41f819a601e8f17b00e7a4eba8a9af4c4b3fdd31d555ccf70058d9f1b7fae54be07f4fee34eb1aacb39a1f7b6fc92abfb714bc2daced46244ccab91917be3d8271a995636b24aa44ff97e3033f41262b2dad5ce2b31734e4dd3912c5838eebdcc079bbb23c1d9a6f36aa31309676c258abac7a2564fd6f7101c1fdb441018a24d25672826953caa03b6717e26e8af1c38507dd570bdedf1cb270c376630823f101577ca503a7ed99eca485da2e875aedf7758472c378c91dce99bbdc44ee9500ed1e5c864bc88ba518585c7e6de5e94d26ee216dd8a5e06c5d2fc740123976c9588787b54998cccb42a9b8d6c46468900527bc741938e78ab4577b1e211be938b9f77888cbdc7bd3787148a6d1653eb0e17603df69d67db30fa4857e11edec461e01e3e02cea2c7d2c5ddd3b0d838ccceae7ebf1781d11d1bb741db7fe1a7b39bdc22b7275d8456ee325424d33829d364270b1ecebb389318c7f0cb1f1c334f05d1d5e26472f2cd07f5d8025ea266e9436f6f30b4b01b57f2780b2898f3820ebd7b98a97776f9db52767b6c05efa5542b39df1245b6cd761da8bcc84fb62e3ea140a133c1ecd3af22c5d7d49ba220061847a7f8b99643fafc79d9404de68e48c4d49a3936f7878d68efc0951aa89bf89fd829dd021fac27712f0f046e70d2d33a8a1fc05554a16d26669a9adb33bb41aaff43df7d4da01032565bb0240296875170ad013260ac9347a54952cb543cb71cdd666f2258d09d1ebb69783b52803a12c25a5b58368b4a9696f438dcc679c6c9b341ced022554000","mixHash":"0x00000000000000000000000000000000000000000000000000000000000002ee","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let source_66277001 = deser_header(
        r#"{"parentHash":"0x8af6d275337e124d1489f4bb67d0102fe4c47a13066e804aa27060cfad181742","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0xf9814d93b4d904aaa855cbd4266d6eb0ec1aa478","stateRoot":"0xe85c95122601ff76eac24cae99a3ada210cf5d86d8730ee7344cbce3f2532760","transactionsRoot":"0x770760783a1d58f1566f3e71723f5810ab98543c5ae249b4d9a4029b989d3a46","receiptsRoot":"0x46080f8e01096c3f805607ff185f0bad0cbe6378e57eaf57fd58abd89fba1cee","logsBloom":"0x02313283e8d300428107046492030c011535080a5a050e072c09d01c06a9e0042c869b88101e8c00ef15612937864057532ea9406d211540c6a083ae802820d28429961f2cc00868030454dea008022e2215540101e6b92a10670205c801c406503c61a0120a40412c0b80a0d2920e078902a4210824cf9012289570a4141b492275a6e40f4664429098a10879c14c91e9278c41232a100864c023c404c80c2a02054604850080300b0157ea8220841990b1507a640214482e1b0208202802aab144194241030005638e0e2880c280a131ae5143ab48009c6c9a48030b85a21008384a53392cd4e003515284409481e1d906c81020650d4858c7194472083d10","difficulty":"0x2","number":"0x3f34e89","gasLimit":"0x5f5e100","gasUsed":"0x80a9f3","timestamp":"0x69018a4c","extraData":"0xd883010513846765746888676f312e32342e30856c696e7578000000098d24ac79d8eff5aa0ca90be72f50a04e5cbc13eadb7050f47ca49dfec51725a21af4f30628236628f4d1067e015458309c69f0542e1897775e97fd99165ad47374381700","mixHash":"0x00000000000000000000000000000000000000000000000000000000000001f4","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let target_66277002 = deser_header(
        r#"{"parentHash":"0x3b965a82887f5504691d4196c9139301c63914219fa9da4198de316f49ecdbcf","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0xf9814d93b4d904aaa855cbd4266d6eb0ec1aa478","stateRoot":"0xa6884c4a3b5856cfb794e6169bea8bbd5acae2c2a6e2d6380bd7826b4d5a0122","transactionsRoot":"0xf2a1f37dd94415e72226f891e7d5032c9eb9b119387e04de41ecac6f83f0b87b","receiptsRoot":"0xc6b40e92a89f46783ae75cf662cba26a39dcacc2a2882332e31eebd6b57ce581","logsBloom":"0xff75fffff7fb7fdfffefffffd7ff7967dfffffeffe7ffff7f7dffbfd777fe3f7dfffffdfffffd7a7fff77dbfffffeffffffffffffffffffff7fbfffd1ffdfbfff6ffffffffffbfffcd7fffdffeff9eb7efbfbeff77fef97ff9ffdffffefffdbfdeffefffffdfef7fffdfbfbfbfffffffdbdfff5ffdffffeefbfffefdf77ffffffff7feff7ffff7f3fcfffffffffffffffdfffcfffbfbfbbbfffffffef96e77fffedfffffffb99fbf9ffffff7df7ffffffdfbfbffff7f5d3dfffffeeff7fefff3ffdf5fffffffbfff5cddfdffffffffebfffd7ff7feffbffdeffb6fefddf7fefffffdfff77bfff7eef7fffffff7bbfbfbdffffdfdfbf7ffff5fffffff7febfff7","difficulty":"0x2","number":"0x3f34e8a","gasLimit":"0x5f5e100","gasUsed":"0x3f9e6d7","timestamp":"0x69018a4d","extraData":"0xd883010513846765746888676f312e32342e30856c696e7578000000098d24acf8b5831fbeeeb860b035e337b926a15274afcb3609f2bfa762bb16770dabc3fb5c3d1ca8623c4787ee5780d75bf8193ae45a58b32d08c88e14865a9f5f367ed4bd90386b6c93b91abfc772b5a099a8f30269357e41e97a946087bfe22424ff3b4ea1c3b68d06197df84c8403f34e82a00280b45f05aca9b4fd2ded2a3ae1ebf516812e0bcabef5087e8939411c9e3cdf8403f34e89a03b965a82887f5504691d4196c9139301c63914219fa9da4198de316f49ecdbcf80b27d7ea7695071341153caa7e6c97b403101623bce0f8068556d840a4a718ffe5b6c514f12f9c72aba1d47bf6158104ca7570f854989e60c60d4a32d77c9d2e401","mixHash":"0x00000000000000000000000000000000000000000000000000000000000000fa","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );
    let attestation_66277003 = deser_header(
        r#"{"parentHash":"0x2f0e34bd0e9e8031258d8fe6026aa660dcc671ced465d04cf3eff6ccfce6edba","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0xf9814d93b4d904aaa855cbd4266d6eb0ec1aa478","stateRoot":"0xc34dc004257713045164ca683414120657f5e25a4c10b67d6c2b3216b4c91632","transactionsRoot":"0xd09aa77ea50bed8f1cde8cb22d44a6c9374f4d543810d151766a8f9e8eab0d41","receiptsRoot":"0x3fe05f87e45740c34b5ca8021086531c8d4908bd7b7681d798163cb3320d6905","logsBloom":"0xcf6fbfcceac85d4fc931bdfc92d99f4605dada61b23d7493adc957ff47aaa4b7de8ef90a9bff913a6f82f820efb3e4f2eb86d8e717437f5147e16bbd40f7f581d43a9ede27ca92ec7310859db0110ab6aff69fb945ee883aab5f51e2afb1b46a44bc51eaca7b8c4abc27ecbf9c600f773a31d6c13cedceea92f5f650c64d43dbeab7d2e113ddc47ad5bef7f8fef99d87e33fed3d2f764acba3cf61f267750ebc46de357ffc28ecf7ebd7dbca8fe4c4516320fb7a6e9a28accfcf52483a5d7ee3a2ce1f4e0bbb074f61aee563bc268b01f55fdf662ea814ff7eba4ca7fe54ee49a8ba6b1336b77aeaa5ec2ea5a119bb799af2bebc2cb48b4a588f7b7c62841db3","difficulty":"0x2","number":"0x3f34e8b","gasLimit":"0x5f5e100","gasUsed":"0x28014e3","timestamp":"0x69018a4e","extraData":"0xd883010513846765746888676f312e32342e30856c696e7578000000098d24acf8b5831fbeeeb860ab77d3e4e6da0526882887ca8d7e84e423f7ec805cc1bca7e65cc53e869fc5aa0f5f63587ec5dce701b24bc389dcee7b049485f2ee2278558fca1d9be9f5803b5149ba33e74959a0472b5094c4b574ccc929ac7c948c94a81d66743be83909c9f84c8403f34e89a03b965a82887f5504691d4196c9139301c63914219fa9da4198de316f49ecdbcf8403f34e8aa02f0e34bd0e9e8031258d8fe6026aa660dcc671ced465d04cf3eff6ccfce6edba8098f5f3621293af90d38a9c2aa86fcbb6f7c33f97257d434f61cb4f41f609ccb66dfe872e2c588821b0401791d05d09f267fe3db48c0f839c95b21f640257127d01","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x0","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","blobGasUsed":"0x0","excessBlobGas":"0x0","parentBeaconBlockRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","requestsHash":"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}"#,
    );

    let (_, valset) = parse_epoch_rotation_header_extra_data(&hex!("d883010601846765746888676f312e32342e37856c696e7578000000098d24ac151cfdbd2dff70c6e2e30df5012726f87731f381648e9879d77f0f25c8f6348135cef7477c2455f516bec180921d4c669eae7258857327674ace724b598c0df3fd41068ef837e9627a91dd13e453246856d58797ad6583d762abd04e3688a7c071dbc7eb3d0ace1c06baf163fdc8ffc742fec16f09fa468d30778a3c533b944899d33ae3225a3aee0738944092685a336cb6b9ea58836436709a2adc89afc1c041d36ee43ed51b1cb17b9dff14068e594b79a3c401a0bcf9fae9fd86324822fc0bb768f0b7dae76927b23d39544d15d9bcd0c2f33e7510c0de8b42697ca558234a8a81ab85d1ea9d9842484aca571512a78ed805c2398ce055d90fa0327b1467d45a00ddc183798193b50fcb15352095e14e5acf9684652bea56f2f01b7101a225ee33d23f8bcfeba8fcafdc6b6f9016d5a0dd08e4685a13bffd8c2087f66bf7ca2dace7fbbc40c40824e30a84d3fe62a2ddcd5217502aecfe253e6aa0e8d2a06e12438ffed0fe16a0b15df58914a6b751909f0558a9f9af8efca7d46e480fc24478d977dafe7daf5161b38c72e9e1ea4865c288ef5b8054ab58567f7a51a58708c8b40ec592a38ba64c0697de8d78def84b10ab93dbfff6980d1054a2bc561bcf0abf3daf6096849bf03744fd4a49392e4813dc2251d68f6f95f27ba775b851a27d7101438f45fce31816501193239a83ad9a5f4ae5ec7dd886b09a47021461ec6f1971b3558f31e622311e94714398c80573fd531e0e8b4c4c3b456c4a5b9bf67b501c7944185130dd4ad73293e8aa84effdcee7b7adb10448b8be5fc875af7df065a5ee57f2ace2cca77b37bbe2e30fd16481afe8a64fe4dd3aff03d14fb180a05bf6a07e1fdf03eb3ac35bf0256694d7fbe6b6d7b3e0c8a066981de27634c2d17a68333f6d9b0c8cd7e08882c397c6ad92d95f8c279d6ef9ea04a1e2f4c4cdfe7ea6015f367ccb8a239732871adc8829ea2f47e94087c5fbad47b6adc9ae11a5f0da15082a4ded8abaeb73338984c06e2c1af2eb24232e00511e95b24e89291d689f6bedb13d5a398af2ec9bb56c2b4dbe5a06d79911c9899b6f817696acfc90ba8c56b1a3c032a3a0395d0f42f3a00b4f50ce9dc41f819a601e8f17b00e7a4eba8a9af4c4b3fdd31d555ccf70058d9f1b7fae54be07f4fee34eb1aacb39a1f7b6fc92abfb714bc2daced46244ccab91917be3d8271a995636b24aa44ff97e3033f41262b2dad5ce2b31734e4dd3912c5838eebdcc079bbb23c1d9a6f36aa31309676c258abac7a2564fd6f7101c1fdb441018a24d25672826953caa03b6717e26e8af1c38507dd570bdedf1cb270c376630823f101577ca503a7ed99eca485da2e875aedf7758472c378c91dce99bbdc44ee9500ed1e5c864bc88ba518585c7e6de5e94d26ee216dd8a5e06c5d2fc740123976c9588787b54998cccb42a9b8d6c46468900527bc741938e78ab4577b1e211be938b9f77888cbdc7bd3787148a6d1653eb0e17603df69d67db30fa4857e11edec461e01e3e02cea2c7d2c5ddd3b0d838ccceae7ebf1781d11d1bb741db7fe1a7b39bdc22b7275d8456ee325424d33829d364270b1ecebb389318c7f0cb1f1c334f05d1d5e26472f2cd07f5d8025ea266d849d1df66bff1c2739b4399425755c2e0fabbaba0bbbfbf2714045f3740e000f297f3e810118f9082cc306c235a23bc1752b8c812fe5ad273219b09675ae356cf2d2d27f8b99643fafc79d9404de68e48c4d49a3936f7878d68efc0951aa89bf89fd829dd021fac27712f0f046e70d2d33a8a1fc05554a16d26669a9adb33bb41aaff43df7d4da0f8de5e61322302b2c6e0a525cc842f10332811bf8e69853df9edb142b5d596f93bfa14253a733cb9d2d5a7ed1fc345e248a8cae7f23f438930123eebf61c98785d846a8bf9814d93b4d904aaa855cbd4266d6eb0ec1aa4789169fa34c99e4a6c5728c129eaf21ea1eebf9af84924ef9544c22821b4bcddbd0f14217e63c38a5ed148431c35c79c2410f8b5831effffb860a7d6dca4ccd4debe5b9fd068bcaa353ca9e2dbb8375f284d8195ed853dbbf99ed0e8716223d6013a03dabd9039e21e8f07d42a126ac87fa8d5dc162f8eb793ac061903187877830e5c3756e0cacc2bd47ca781d53271b0cae76a362e41f3c907f84c8403f34a9ea044e87e706232c25283dfa53443028df61f61d2a81a80a82d55d84920782c56088403f34a9fa0d706e41e775cf07d9ceb59233c6260ed4cc8fb0deda974e75f6ba61983846e2b80fd245d30574bf8dde140005cbeb1202b368cca117a1ec83579bdf71619f1fdc82792557f8d4c44096154d744fec1e9a84cec4dbb07dcede8b78bbd87c51bd50000")).unwrap();

    let ctx = BlstContext {
        current_timestamp: Timestamp::from_secs(1761638144),
        epoch_valsets: [(66276000, valset)].into_iter().collect(),
    };

    let chain = [
        ancestor_66277000.clone(),
        source_66277001.clone(),
        target_66277002.clone(),
        attestation_66277003.clone(),
    ];

    // dbg!(source_66277000.hash(), target_66277001.hash());

    let (header, valset) =
        verify_header(&chain, Duration::from_secs(604800), 66276000, ctx.clone()).unwrap();

    assert_eq!(header, &ancestor_66277000);
    assert_eq!(
        valset,
        Some((
            66277000,
            parse_epoch_rotation_header_extra_data(&ancestor_66277000.extra_data)
                .unwrap()
                .1
        ))
    );
}
